# 可变参数（一维数据）
def calcOne(numbers):
	sum=0
	for x in numbers:
		sum=sum+x*x
	return	sum

def calcTwo(*numbers):
	sum=0
	for x in numbers:
		sum=sum+x*x
	return sum

print(calcOne([1,2,3]))
print(calcOne((1,2,3)))
print(calcTwo(1,2,3))

# 关键字参数（dic二级数组）
def person(name,age,**kw):
	print('name:',name,'age:',age,'other:',kw)

person('Michael',30)

person('Michael',20,city='beihing')
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)

def product(*args):
    sub=1
    for x in args:
    	sub*=x
    return sub

print(product(5))
print(product(2,3))

# 命名关键字参数
def myperson(name,age,**kw):
	if 'city' in kw:
		print("city is in the kw")
	if 'job' in kw:
		print("job is in the kw")
	print('name:',name,'age:',age,'other:',kw)

myperson('Jack',34,city='beihing',addr='choayao',zipcode='2333343')

# 添加命名关键字参数
def restrickMyPerson(name,age,*,city,job):
	print(name,age,city,job)

restrickMyPerson('Jack', 24, city='Beijing', job='Engineer')

# restrickMyPerson('Jack', 24, city='Beijing', job1='Engineer')
def restrickMyPersonTwo(name,age,*args,city,job):
	pass
# 使用命名关键字参数时，要特别注意，如果没有可变参数，就必须加一个*作为特殊分隔符。如果缺少*，Python解释器将无法识别位置参数和命名关键字参数：

# 定义函数的时候，我们把参数的名字和位置确定下来，函数的接口定义就完成了。对于函数的调用者来说，只需要知道如何传递正确的参数，以及函数将返回什么样的值就够了，函数内部的复杂逻辑被封装起来，调用者无需了解。

# Python的函数定义非常简单，但灵活度却非常大。除了正常定义的必选参数外，还可以使用默认参数、可变参数和关键字参数，使得函数定义出来的接口，不但能处理复杂的参数，还可以简化调用者的代码。


def power(x, n):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s
# 对于这个修改后的power(x, n)函数，可以计算任意n次方：


# 使用命名关键字参数时，要特别注意，如果没有可变参数，就必须加一个*作为特殊分隔符。如果缺少*，Python解释器将无法识别位置参数和命名关键字参数：

def person(name, age, city, job):
    # 缺少 *，city和job被视为位置参数
    pass

# 参数组合
# 在Python中定义函数，可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数，这5种参数都可以组合使用。但是请注意，参数定义的顺序必须是：必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
def f1(a,b,c=0,*args,**kw):
	print('a=',a,'b=',b,'c=',c,'args=',args,'kw=',kw)
def f2(a,b,c=0,*,d,**kw):
	print('a=',a,'b=',b,'c=',c,'d=',d,'args=',args,'kw=',kw)

f1(1,2)

args=(1,2,3,4)
kw={'d':33,'x':'kw'}
print("f1调用结果:")
f1(*args,**kw)

args=(1,2,3)
kw={'d':'ddd','kw':'kwtwo'}
f2(*args,**kw)

# 任意函数，都可以通过类似func(*args, **kw)的形式调用它，无论它的参数是如何定义的

def improveProduct(x,y,*args):
	retValue=x*y
	for item in args:
		retValue*=item
	return retValue
def testImproveProduct():
	if improveProduct(5,6)!=30:
	   print('测试一个数失败')
	elif improveProduct(5,6,7)!=210:
		print('测试三个数积失败')
	else:
		try:
			improveProduct()
		except Exception as e:
			print(e)
		finally:
			print("the is the last finally")

testImproveProduct()


def fact(n):
    if n==1:
        return 1
    return n*fact(n-1)

print(fact(100))

def fact2(n):
    return fact_iter(n, 1)

def fact_iter(num, product):
    if num == 1:
        return product
    return fact_iter(num - 1, num * product)

print(fact2(100))


# 高级特性
# 切片
L=list(range(100))
print(L[:10:2])

r=[]
for x in range(5):
	r.append(L[2*x])

rr=[L[2*x] for x in range(5)]
print(r)
print(rr)


d = {'a': 1, 'b': 2, 'c': 3}
for x in d:
	print(x)

for x in d.values():
	print(x)

for key,value in d.items():
	print(key,":",value)

from collections import Iterable
print(isinstance('abc',Iterable))
for i,value in enumerate(['a','b','c']):
	print(i,value)

def SetLower(x):
	if isinstance(x,str):
		return x.lower()
	return x

L1 = ['Hello', 'World', 18, 'Apple', None]
L2=[ SetLower(x) for x in L1]
print(L2)
L2=[ x.lower() for x in L1 if isinstance(x,str)]
print(L2)

# 装饰器的使用

def log(func):
	import functools
	@functools.wraps(func)
	def wrapper(*args,**kw):
		print("call %s():" % func.__name__)
		return func(*args,**kw)
	return wrapper

def log2(text):
	def decorator(func):
		import functools
		@functools.wraps(func)
		def wrapper(*args,**kw):
			print('%s %s' % (text,func.__name__))
			return func(*args,**kw)
		return wrapper
	return decorator



@log2("excute")
@log
def now():
	print("this is now function print out")

now()


# 偏函数的使用 functool.partial
import functools
# print(dir(functools))
int2=functools.partial(int,base=2)

print(int2('1000'))

from student import Student
# print(dir(student.Student(None)))
stu_ver=Student('bob',50)
print('bob\'s grad is %s' % stu_ver.get_grad())
print(student.Student.count)
stu_ver2=Student('bob2',50)
print(stu_ver2.count)

